/**
 * 用户编辑接口测试用例
 *
 * Created by snowingsea on 2020/02/02.
 */
const crypto = require('crypto');
const randomstring = require('randomstring');
const WebSocket = require('ws');

const chai = require('chai');
const should = chai.should(); // eslint-disable-line no-unused-vars
chai.use(require('chai-http'));

const common = require('./../../common');
const Administrator = require('./../../../models/administrator');
const uri = require('./../uri');
const { roleKind, statusKind } = require('./../../../../phoenix/models/users');
// const license = require('./../../../../phoenix/models/license');

module.exports = describe('/PUT users/:id.json', function () {
  const administrator = new Administrator();
  const newUserIds = [];
  let user = {};
  function url(userId) {
    if (!userId) userId = user.userId;
    return `/users/${userId}.json`;
  }
  before(function (done) {
    administrator.createRandomUser()
      .then((res) => {
        user = res;
        newUserIds.push(user.userId);
        done();
      })
      .catch(done);
  });
  after(function (done) {
    administrator.removeUsers(newUserIds)
      .then(() => {
        done();
      })
      .catch(done);
  });

  common.should.be.user(uri, url, 'put');
  common.should.be.administrator(uri, url, 'put');

  // 正常请求编辑
  [
    {},
    { username: randomstring.generate(16) },
    { nickname: randomstring.generate(16) },
    { status: statusKind.offline },
    { roles: [roleKind.administrator] },
    { roles: [roleKind.tester] },
    { roles: [roleKind.administrator, roleKind.tester] },
    { roles: [roleKind.tester | roleKind.administrator] }, // eslint-disable-line no-bitwise
    { roles: [roleKind.tester | roleKind.administrator, roleKind.tester] }, // eslint-disable-line
  ].forEach((edit, index) => {
    it(`it should ${index === 0 ? 'PUT' : 'put'} a user with ${JSON.stringify(edit)}`, function (done) {
      administrator.login()
        .then(() => {
          chai.request(uri)
            .put(url())
            .set('Authorization', `Bearer ${administrator.token.accessToken}`)
            .query(edit)
            .end((err, res) => {
              res.should.have.status(200);
              common.should.be.userMessage(res.body);
              res.body.userId.should.be.eql(user.userId);
              Object.keys(edit).forEach((key) => {
                if (key === 'roles') {
                  let role = 0;
                  edit[key].forEach((itemRole) => {
                    role |= itemRole; // eslint-disable-line no-bitwise
                  });
                  res.body.role.should.be.eql(role);
                } else {
                  res.body[key].should.be.eql(edit[key]);
                }
              });
              done();
            });
        })
        .catch(done);
    });
  });

  // 更改密码
  it('it should login successfully with the new password when change the password', function (done) {
    const newPassword = crypto.createHash('sha256').update(randomstring.generate(16)).digest('hex');
    let newUser;
    administrator.createRandomUser()
      .then((user) => {
        newUser = user;
        newUserIds.push(user.userId);
        return administrator.login();
      })
      .then(() => {
        chai.request(uri)
          .put(url(newUser.userId))
          .set('Authorization', `Bearer ${administrator.token.accessToken}`)
          .send({ password: newPassword })
          .end((err, res) => {
            res.should.have.status(200);
            common.should.be.userMessage(res.body);
            res.body.userId.should.be.eql(newUser.userId);
            newUser.password = newPassword;
            newUser.token = {};
            newUser.login()
              .then(() => {
                common.should.be.tokenMessage(newUser.token);
                done();
              })
              .catch(done);
          });
      })
      .catch(done);
  });

  // 下线在线用户
  [
    { status: statusKind.offline, name: 'offline' },
  ].forEach((operator) => {
    it(`it should ${operator.name} the online user`, function (done) {
      let newUser;
      administrator.createRandomUser()
        .then((user) => {
          newUserIds.push(user.userId);
          newUser = user;
          return newUser.login();
        })
        .then(() => administrator.getUser(newUser.userId))
        .then(({ status }) => {
          status.should.be.eql(statusKind.online);
          chai.request(uri)
            .put(url(newUser.userId))
            .set('Authorization', `Bearer ${administrator.token.accessToken}`)
            .query({ status: operator.status })
            .end((err, res) => {
              res.should.have.status(200);
              common.should.be.userMessage(res.body);
              res.body.userId.should.be.eql(newUser.userId);
              res.body.status.should.be.eql(operator.status);
              setTimeout(() => {
                newUser.ws.readyState.should.be.eql(WebSocket.CLOSED);
                done();
              }, 2000);
            });
        })
        .catch(done);
    });
  });

  // 由于用户名已存在而导致的编辑失败
  it('it should fail to put user\'s username when the name is exists', function (done) {
    let existUserName;
    administrator.createRandomUser()
      .then(({ username, userId }) => {
        newUserIds.push(userId);
        existUserName = username;
        return administrator.login();
      })
      .then(() => {
        chai.request(uri)
          .put(url())
          .set('Authorization', `Bearer ${administrator.token.accessToken}`)
          .query({ username: existUserName })
          .end((err, res) => {
            res.should.have.status(409);
            common.should.be.errorMessage(res.body);
            done();
          });
      })
      .catch(done);
  });

  // 编辑不存在的用户
  it('it should fail to put a user when the user is not exists', function (done) {
    let newUserId;
    administrator.createRandomUser()
      .then(({ userId }) => {
        newUserIds.push(userId);
        newUserId = userId;
        return administrator.removeUser(newUserId);
      })
      .then(() => administrator.login())
      .then(() => {
        chai.request(uri)
          .put(url(newUserId))
          .set('Authorization', `Bearer ${administrator.token.accessToken}`)
          .end((err, res) => {
            res.should.have.status(404);
            common.should.be.errorMessage(res.body);
            done();
          });
      })
      .catch(done);
  });

  // 不可修改为超级用户角色
  it('it should fail to add superuser role', function (done) {
    administrator.login()
      .then(() => {
        chai.request(uri)
          .put(url())
          .set('Authorization', `Bearer ${administrator.token.accessToken}`)
          .query({ roles: [roleKind.superUser] })
          .end((err, res) => {
            res.should.have.status(416);
            common.should.be.errorMessage(res.body);
            done();
          });
      })
      .catch(done);
  });

  // 已达许可证最大用户数限制
  /*
  it('it should fail to edit user when the count of users reaches the limit', function (done) {
    administrator.login()
      .then(() => administrator.replaceLicense(license.statusKind.exceedTester))
      .then(() => administrator.createRandomAdministrator())
      .then(({ userId }) => {
        newUserIds.push(userId);
        chai.request(uri)
          .put(url(userId))
          .set('Authorization', `Bearer ${administrator.token.accessToken}`)
          .query({ roles: [roleKind.tester] })
          .end((err, res) => {
            administrator.replaceLicense(license.statusKind.normal)
              .then(() => {
                res.should.have.status(403);
                common.should.be.errorMessage(res.body);
                done();
              })
              .catch(done);
          });
      })
      .catch(done);
  });
   */
});
